drive: fix two upload failures caused by Proton backend changes#1
drive: fix two upload failures caused by Proton backend changes#1lmwashere wants to merge 1 commit intorclone:masterfrom
Conversation
This commit fixes two bugs that prevent file uploads to Proton Drive:
--- Bug 1: handleRevisionConflict ignores ReplaceExistingDraft when
GetRevisions returns 2501 ---
When a previous upload attempt fails after the file draft is created but
before blocks are committed, a broken draft remains. On the next attempt
the draft is found (2500 "file already exists"), and GetRevisions is called
to decide what to do with it. However, broken drafts return 422/2501 from
the /revisions endpoint, causing handleRevisionConflict to return an error
immediately — even when ReplaceExistingDraft=true.
Fix: if GetRevisions fails AND ReplaceExistingDraft is set AND the link is
in draft state, treat it as a broken draft and delete the link so the caller
can retry from scratch.
--- Bug 2: block uploads missing required Verifier.Token ---
Proton's storage backend now requires a Verifier.Token per block in the
POST /drive/blocks request. Without it, the storage server rejects block
uploads with HTTP 422 / Code=200501 "Operation failed: Please retry".
The token is computed by fetching a VerificationCode for the revision via:
GET /drive/v2/volumes/{volumeID}/links/{linkID}/revisions/{revisionID}/verification
then XOR-ing it with the leading bytes of each block's ciphertext (algorithm
sourced from the official Proton Drive JS SDK in ProtonDriveApps/sdk).
Also bumps go-proton-api to v1.0.1-0.20260218123427-1a63a293e3a2 which
updates the default API host from mail.proton.me/api to drive-api.proton.me.
Note: the JS SDK performs an additional client-side decryption check before
computing the XOR token (to detect bit-flips / bad hardware). That step is
not implemented here; the server-side manifest signature still provides
end-to-end integrity verification. A future improvement could add it.
This fix was identified and generated with Claude Code (AI assistant) by a
non-programmer user (GitHub: lmwashere). It has not been independently
reviewed by a Go or cryptography expert. Expert review before merging is
strongly recommended.
Reproducer: rclone copy <file> proton: --verbose
Expected: upload succeeds
Actual: 422 POST fra-storage.proton.me/storage/blocks (Code=200501)
followed by 422 GET .../revisions (Code=2501) on retry
Test Results with This FixIntegration tests run on rclone backend using this PR: ✅ Passing Tests
❌ Still Failing
SummaryThis PR fixes the 422 block upload errors ✅, but move/rename operations still fail with Code 2000. A separate fix for session key reuse during move is needed. Test command: |
|
Thanks for running those integration tests, @mcanevet — really helpful data! Glad to hear the 422 block upload errors are resolved ✅. The FsMove / FsDirMove Code 2000 failures are a known separate issue related to session key reuse during move operations — outside the scope of this PR. I agree a dedicated fix would be the right approach there. Hopefully the maintainers can take a look now that there's community-verified test coverage on this. |
This fixes two bugs that prevent file uploads to Proton Drive (broken as of ~Feb 2026):
Bug 1:
handleRevisionConflictignoresReplaceExistingDraftwhenGetRevisionsreturns 2501When a previous upload attempt fails after the file draft is created but before blocks are committed, a broken draft remains. On the next attempt the draft is found (2500 "file already exists"), and
GetRevisionsis called to decide what to do with it. However, broken drafts return 422/2501 from the/revisionsendpoint, causinghandleRevisionConflictto return an error immediately — even whenReplaceExistingDraft=true.Fix: if
GetRevisionsfails ANDReplaceExistingDraftis set AND the link is in draft state, treat it as a broken draft and delete the link so the caller can retry from scratch.Bug 2: block uploads missing required
Verifier.TokenProton's storage backend now requires a
Verifier.Tokenper block in thePOST /drive/blocksrequest. Without it, the storage server rejects block uploads with HTTP 422 / Code=200501.The token is computed by fetching a
VerificationCodefor the revision via:then XOR-ing it with the leading bytes of each block's ciphertext (algorithm sourced from the official Proton Drive JS SDK in ProtonDriveApps/sdk).
Also bumps
go-proton-apitov1.0.1-0.20260218123427-1a63a293e3a2which updates the default API host frommail.proton.me/apitodrive-api.proton.me(see rclone/go-proton-api#2).Reproducer:
rclone copy <file> proton: --verboseExpected: upload succeeds
Actual:
422 POST fra-storage.proton.me/storage/blocks (Code=200501)followed by422 GET .../revisions (Code=2501)on retryThis fix was identified and generated with Claude Code (AI assistant) by a non-programmer user (GitHub: lmwashere). It has not been independently reviewed by a Go or cryptography expert. Expert review before merging is strongly recommended.